class MyPromise {
  state = "pending" // 状态 'pending'  'fulfilled'  'rejected'
  value = undefined // 成功后的值
  reason = undefined // 失败后的原因

  resolveCallbacks = [] // pending状态下，存储成功的回调
  rejectCallbacks = [] // pending状态下，存储失败的回调
  constructor(fn) {
    const resolveHandler = (value) => {
      if (this.state === "pending") {
        this.state = "fulfilled"
        this.value = value
        this.resolveCallbacks.forEach((fn) => fn(this.value))
      }
    }
    const rejectHandler = (reason) => {
      if (this.state === "pending") {
        this.state = "rejected"
        this.reason = reason
        this.rejectCallbacks.forEach((fn) => fn(this.reason))
      }
    }
    try {
      fn(resolveHandler, rejectHandler)
    } catch (e) {
      rejectHandler(e)
    }
  }
  then(fn1, fn2) {
    // 当pending 状态下，fn1 fn2会被存储到callbacks中
    fn1 = typeof fn1 === "function" ? fn1 : (v) => v
    fn2 = typeof fn2 === "function" ? fn2 : (e) => e
    if (this.state === "pending") {
      // 存储函数
      const p1 = new MyPromise((resolve, reject) => {
        this.resolveCallbacks.push(() => {
          try {
            const newValue = fn1(this.value)
            resolve(newValue) // p1.value
          } catch (err) {
            reject(err)
          }
        })
        this.rejectCallbacks.push(() => {
          try {
            const newReason = fn2(this.reason)
            reject(newReason)
          } catch (err) {
            reject(err)
          }
        })
      })
      return p1
    }

    if (this.state === "fulfilled") {
      const p1 = new MyPromise((resolve, reject) => {
        try {
          const newValue = fn1(this.value)
          resolve(newValue)
        } catch (err) {
          reject(err)
        }
      })
      return p1
    }

    if (this.state === "rejected") {
      const p1 = new MyPromise((resolve, reject) => {
        try {
          const newReason = fn2(this.reason)
          reject(newReason)
        } catch (err) {
          reject(err)
        }
      })
      return p1
    }
  }

  // 就是then的一个语法糖，简单模式
  catch(fn) {
    return this.then(null, fn)
  }
}

MyPromise.resolve = function (value) {
  return new MyPromise((resolve, reject) => resolve(value))
}

MyPromise.reject = function (value) {
  return new MyPromise((resolve, reject) => reject(value))
}

MyPromise.all = function(promiseList = []) {
  const p1 = new MyPromise((resolve, reject) => {
    const result = [] // 存储promiseList所有的结果
    const length = promiseList.length
    let resolvedCount = 0

    promiseList.forEach(p => {
      p.then(data => {
        result.push(data)

        // resolvedCount必须在then里面做++
        // 不能用 index
        resolvedCount++
        if(resolvedCount === length) {
          // 已经遍历到了最后一个promise
          resolve(result)
        }
      }).catch(err => {
        reject(err)
      })
    })
  })
  return p1
}

MyPromise.race = function (promiseList = []) {
  let resolved = false // 标记
  const p1 = new Promise((resolve, reject) => {
    promiseList.forEach(p => {
      p.then(data => {
        if(!resolved) {
          resolve(data)
          resolved = true
        }
      }).catch((err) => {
        reject(err)
      })
    })
  })
  return p1
}
